package com.ruoyi.activiti.controller;

import com.github.pagehelper.Page;
import com.ruoyi.activiti.domain.dto.ProcessDefinitionDto;
import com.ruoyi.activiti.domain.vo.ProcessDefinitionVo;
import com.ruoyi.activiti.domain.vo.ProcessViewerVo;
import com.ruoyi.activiti.service.ProcessDefinitionService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.impl.util.IoUtil;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;
import java.util.List;

/*
 * 流程定义相关操作
 * */
@RestController
@RequestMapping("/process/instance")
public class ProcessInstanceController extends BaseController {

    @Autowired
    private ProcessDefinitionService processDefinitionService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ProcessRuntime processRuntime;

    /*
     * 查询流程定义列表
     * */
    @GetMapping("/list")
    public TableDataInfo instances(ProcessDefinitionDto processDefinition) {
        Page<ProcessDefinitionVo> processDefinitionVos =
                processDefinitionService.listProcessDefinition(processDefinition);
        return getDataTable(processDefinitionVos);
    }

    /**
     * 挂起激活流程实例
     * @param instanceId 流程实例id
     * @param suspendState 状态1激活 2挂起
     * */
    @PostMapping("/state")
    public AjaxResult suspendInstance(String instanceId, String suspendState) {
        if(StringUtils.isBlank(instanceId)){
            throw new RuntimeException("流程实例Id不能为空");
        }
        if(StringUtils.isBlank(suspendState)){
            throw new RuntimeException("流程实例状态不能为空");
        }
        if ("1".equals(suspendState)) {
            // 当流程实例被挂起时，无法通过下一个节点对应的任务id来继续这个流程实例。
            // 通过挂起某一特定的流程实例，可以终止当前的流程实例，而不影响到该流程定义的其他流程实例。
            // 激活之后可以继续该流程实例，不会对后续任务造成影响。
            // 直观变化：act_ru_task 的 SUSPENSION_STATE_ 为 2
            repositoryService.activateProcessDefinitionById(instanceId);
        } else if ("2".equals(suspendState)) {
            repositoryService.suspendProcessDefinitionById(instanceId);

        }
        return AjaxResult.success(suspendState.equals("1") ? "流程实例激活成功":"流程实例挂起成功");
    }

    /**
    * 删除流程定义
    * @param deploymentId 流程部署的Id
    * */
    @DeleteMapping("/{deploymentId}")
    public AjaxResult deleteInstance(@PathVariable("deploymentId") String deploymentId) {
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
                .deploymentId(deploymentId)
                .list();
        if(!list.isEmpty()) {
            // 存在流程实例的流程定义
            throw new RuntimeException("删除失败，存在运行中的流程实例");
        }
        repositoryService.deleteDeployment(deploymentId, true);
        return AjaxResult.success("流程实例删除成功");
    }
    /**
    * 查看流程
     * @param deploymentId 部署id
     * @param name 流程名称
    * */
    @GetMapping("/viewer")
    public AjaxResult viewer(@RequestParam String deploymentId, @RequestParam String name) throws Exception {
        InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, name);
        byte[] bytes = IoUtil.readInputStream(resourceAsStream, name);
        String bpmnxML = new String(bytes, "utf-8");
        ProcessViewerVo vo = new ProcessViewerVo();
        vo.setModelName(name);
        vo.setBpmnXml(bpmnxML);
        return AjaxResult.success(vo);
    }

}
